package com.credithc.signature.manager.mq;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.credithc.signature.common.constant.CacheConstant;
import com.credithc.signature.common.ro.manager.ChannelRo;
import com.credithc.signature.common.ro.manager.TemplateRo;
import com.credithc.signature.common.service.ChannelService;
import com.credithc.signature.common.utils.CacheUtil;
import com.credithc.signature.manager.constant.ModifyConstant;
import com.credithc.signature.manager.service.TemplateMService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

@Component
@Slf4j
public class MessageReceiver {

    @Bean
    public MessageConverter messageConverter() {
        ContentTypeDelegatingMessageConverter messageConverter = new ContentTypeDelegatingMessageConverter();
        messageConverter.addDelegate(MediaType.APPLICATION_JSON_VALUE, new Jackson2JsonMessageConverter());
        messageConverter.addDelegate(MediaType.TEXT_PLAIN_VALUE, new SimpleMessageConverter());
        return messageConverter;
    }

    @Autowired
    private ChannelService channelService;


    @Autowired
    TemplateMService templateService;

    @RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "signature_product"),
            exchange = @Exchange(value = "productExchange", type = ExchangeTypes.TOPIC),
            key = "product.*")})
    public void receiveModifyProductMessage(String msg, Channel channel, @Headers Map<String, Object> map) {
        log.info("接收到消息" + msg);
        if (checkMessage(channel, map)) {
            return;
        }
        try {
            JSONObject jsonObject = JSONObject.parseObject(msg);
            String modifyType = (String) jsonObject.get("modifyType");
            if (ModifyConstant.EDIT.equals(modifyType)) {
                channelService.update(bulidChannelRo(jsonObject));
            } else {
                throw new RuntimeException("modifyType 取值范围不对");
            }
            channel.basicAck((Long) map.get(AmqpHeaders.DELIVERY_TAG), false);
        } catch (JSONException e) {
            try {
                channel.basicAck((Long) map.get(AmqpHeaders.DELIVERY_TAG), false);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        } catch (Exception e) {
            log.error("处理中台MQ消息时发生异常", e);
        }
    }

    @RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "channel_key"),
            exchange = @Exchange(value = "saas.product.secretkey.exchange", type = ExchangeTypes.TOPIC),
            key = "SIGNATURE")})
    public void receiveChannelKeyMessage(String msg, Channel channel, @Headers Map<String, Object> map) {

        log.info("新增key 接收到消息" + msg);
        if (checkMessage(channel, map)) {
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(msg);
        com.credithc.signature.common.po.Channel channelPo = channelService.selectByChannelNo(jsonObject.getString("code"));
        if (channelPo != null) {
            channelPo.setEncryptKey(jsonObject.getString("secretKey"));
            channelPo.setChannelNo(jsonObject.getString("code"));
            log.info("增加channel_key" + channelPo.toString());
            channelService.updateByPrimaryKeySelective(channelPo);
            log.info("更新成功");
        } else {
            ChannelRo channelRo = bulidChannelRo(jsonObject);
            channelRo.setEncryptKey(jsonObject.getString("secretKey"));
            channelRo.setChannelName(jsonObject.getString("productName"));
            channelService.save(channelRo);
        }

        try {
            channel.basicAck((Long) map.get(AmqpHeaders.DELIVERY_TAG), false);
        } catch (IOException e) {
            log.error("处理中台MQ消息时发生异常", e);
        }
    }

    @RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "tem_status"),
            exchange = @Exchange(value = "saas.approval.status.exchange", type = ExchangeTypes.TOPIC),
            key = "approval.status")})
    public void updateTemplateSts(String msg, Channel channel, @Headers Map<String, Object> map) {

        log.info("接收到消息" + msg);
        if (checkMessage(channel, map)) {
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(msg);
        log.info("转换JSONobject成功");
        TemplateRo templateRo = new TemplateRo();
        templateRo.setId(jsonObject.getLong("callerId"));
        templateRo.setAuditStatus(jsonObject.getInteger("status"));
        templateRo.setApprovalId(jsonObject.getInteger("id"));
        templateService.updateAuditSts(templateRo);
        log.info("修改模板审批状态成功");
        try {
            channel.basicAck((Long) map.get(AmqpHeaders.DELIVERY_TAG), false);
        } catch (IOException e) {
            log.error("处理中台MQ消息时发生异常", e);
        }
    }


    private ChannelRo bulidChannelRo(JSONObject jsonObject) {
        ChannelRo channelRo = new ChannelRo();
        channelRo.setChannelNo(jsonObject.getString("code"));
        channelRo.setChannelAlias(jsonObject.getString("productCode"));
        channelRo.setChannelName(jsonObject.getString("name"));
        return channelRo;
    }

    private boolean checkMessage(Channel channel, @Headers Map<String, Object> map) {
        if (map.get("error") != null) {
            System.out.println("错误的消息");
            try {
                //否认消息
                channel.basicNack((Long) map.get(AmqpHeaders.DELIVERY_TAG), false, true);
                return true;
            } catch (IOException e) {
                log.error("处理中台MQ消息时发生异常", e);
            }
        }
        return false;
    }


}
